22. hashchange & pushState
hashchange & pushState
A common URL can be broken down into several parts:
https://en.wikipedia.org/wiki/Udacity#History
https://- protocolen.wikipedia.org- domain/wiki/Udacity- path#History- fragment identifier
Whenever the protocol, domain, or path parts are altered, the whole page is refreshed with new content. However, if the fragment identifier is changed, an event is fired but the page does not refresh. To learn more about these parts of a URL, check out Mozilla's article on Understanding URLs and their structure.
hashchange
The event that's fired when the fragment identifier is added or changed is the hashchange event. Frameworks use this event to power routing in single page apps.
<!-- new.html -->
<h1>New Page Heading</h1>
<p>New page content. Lorem ipsum...</p>
…and then in a JavaScript file:
// app.js
// when the fragment changes, update the page's content with new data
$(window).on('hashchange', function() {
var newPageUrl = getFragmentIdentifier();
$.get( newPageUrl, function( pageContents ) {
$('#content').html( pageContents );
})
});
If our website were located at http://example.com/, changing the URL to http://example.com/#page.html will load the new page's content into #content element.
pushState
With the advancement of HTML5, the window.history.pushState() object was created. This method will update the contents of the browser's history stack. The signature for pushState is:
window.history.pushState( state, title, url );
The state is an object containing information that will be associated with the new entry on the history stack.
The title is a string. This field is currently ignored.
The url is a string. The provided URL can be an absolute or relative URL but must be of the same origin as the current page.
Let's assume the following about a recent browser session:
- the current page is: https://developer.mozilla.org/en-US/docs/Web/API/History_API
- your browser's history stack is:
…where #3 is the new tab you started from and #1 is the page you were just on before navigating to the current page.
Running the following code in the console:
var state = { 'userId': 13579, 'secret': 'HTML5 is awesome' };
var title = 'A secret page!';
var url = 'https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/HTML5';
history.pushState(state, title, url);
…will change the URL to be https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/HTML5. It does this silently, meaning the page does not reload. The updated history stack is now:
- https://developer.mozilla.org/en-US/docs/Web/API/History_API (← notice this one)
- https://developer.mozilla.org/en-US/docs/Web/API/History/pushState
- https://developer.mozilla.org/
- New Tab
Notice that the URL for the page that you are on is the most recent one in the stack. If you navigate to the Window.history page, the HTML5 URL will be added to the history stack even though the page was never actually visited. The usefulness of this is that if you press the Back button, the browser will actually load MDN's HTML5 page since that was the most recent location in its history.
The way frameworks handle URL management using pushState is that they listen for clicks on links in the application, load new content into the page, and use pushState to update the URL to match the information the page is now displaying.